package com.admin.controller.admin;


import com.system.annotation.Log;
import com.system.constant.CommonConstant;
import com.system.constant.HTTPStatus;
import com.system.emus.BusinessType;
import com.system.entity.Menu;
import com.system.entity.RoleMenu;
import com.system.response.Result;
import com.system.response.menu.MenuDtoResponse;
import com.system.response.vo.RouterVo;
import com.system.service.MenuService;
import com.system.service.TeacherService;
import com.system.util.StringUtils;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotNull;
import java.util.List;

/**
 * <p>
 * 菜单表 前端控制器
 * </p>
 * RequiresAuthentication：当前Subject必须在当前session中已经过认证。
 * @author zfc
 * @since 2023-04-20
 */
@RequiresAuthentication
@Validated
@RestController
@RequestMapping("/menu")
public class MenuController {

    @Autowired
    private TeacherService teacherService;

    @Autowired
    private MenuService menuService;

    @GetMapping("/getMenus")
    @ApiOperation("侧边栏菜单列表")
    public Result getMenus(){
        return menuService.selectMenuTreeByRoleNames();
    }

    @Cacheable(value = "menus",key = "#root.methodName",sync = true)
    @GetMapping ("/all")
    @ApiOperation(value = "查询所有菜单(绑定角色)")
    public Result all(){
        return menuService.getAllMenu();
    }

    @Cacheable(value = "menus",key = "#menuDtoResponse.menuName + '::' + #menuDtoResponse.status",sync = true)
    @PostMapping ("/getMenusList")
    @ApiOperation(value = "条件查询菜单列表")
    public Result getMenusList(@RequestBody MenuDtoResponse menuDtoResponse){
        //这个模糊查询暂定，后续如果实现比较困难就取消
        List<Menu> menuList = menuService.getAllMenuTree(menuDtoResponse);
         List<RouterVo> menuTree = menuService.buildMenus(menuList);
        return new Result().setCode(HTTPStatus.SUCCESS).setData(menuTree);
    }

    @Log(title = "菜单管理",businessType = BusinessType.INSERT)
    @CacheEvict(value = "menus",allEntries = true)
    @RequiresPermissions("admin:menu:add")
    @PostMapping("/addMenu")
    @ApiOperation("新增菜单")
    public Result addMenu(@Validated @RequestBody Menu menu){

        boolean unique = menuService.checkMenuNameUnique(menu);

        if (!unique){
            return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("菜单【"+menu.getMenuName()+"】已存在不能新增。");
        }else if (!menu.getType().equals(CommonConstant.TYPE_DIR) || menu.getParentId()>0){
            //修改不是父菜单，就需要 判断父菜单是否存在
            int parentMenuCount = menuService.checkParentMenuExistById(menu.getParentId());
            if (parentMenuCount<=0){
                return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("您所选的父菜单不存在！");
            }
        }
        boolean addMenuFlg = menuService.addMenu(menu);
        if (addMenuFlg){
            return new Result().setCode(HTTPStatus.SUCCESS).setMessage("新增【"+menu.getMenuName()+"】菜单成功。");
        }else {
            return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("新增【"+menu.getMenuName()+"】菜单失败，请联系管理员。");
        }
    }

    @Log(title = "菜单管理",businessType = BusinessType.UPDATE)
    @CacheEvict(value = "menus",allEntries = true)
    @RequiresPermissions("admin:menu:update")
    @PutMapping("/updateMenu")
    @ApiOperation("修改菜单")
    public Result updateMenu(@Validated @RequestBody Menu menu){
        boolean unique = menuService.checkMenuNameUnique(menu);

        if (!unique){
            return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("菜单【"+menu.getMenuName()+"】已存在不能修改。");
        }else if (!menu.getType().equals(CommonConstant.TYPE_DIR)){
            //修改是父菜单，就需要 判断父菜单下是否有子菜单存在
            int parentMenuCount = menuService.checkParentMenuExistById(menu.getParentId());
            if (parentMenuCount<=0){
                return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("您所选的父菜单不存在！");
            }
        }

        boolean updateMenu = menuService.updateMenu(menu);
        if (updateMenu){
            return new Result().setCode(HTTPStatus.SUCCESS).setMessage("操作【"+menu.getMenuName()+"】菜单成功。");
        }else{
            return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("操作【"+menu.getMenuName()+"】菜单失败，请联系管理员。");
        }
    }

    @Cacheable(value = "menus",key = "#root.methodName +'::'+ #id")
    @GetMapping("/selectMenuById")
    @ApiOperation("查询菜单通过菜单id")
    public Result selectMenuById(@NotNull(message = "编号不能为空") Integer id){
        Menu menu = menuService.selectMenuById(id);

        //判断菜单是否存在，为空就算不存在
        if (StringUtils.isNull(menu)){
            return new Result().setCode(HTTPStatus.NO_CONTENT).setMessage("该菜单不存在。");
        }else{
            return new Result().setCode(200).setData(menu);
        }
    }

    @Log(title = "菜单管理",businessType = BusinessType.FREEZE)
    @CacheEvict(value = "menus",allEntries = true)
    @RequiresPermissions("admin:menu:delete")
    @DeleteMapping("/deleteMenu")
    @ApiOperation("删除菜单（修改菜单的删除状态）")
    public Result updateMenuStatus(@RequestBody Menu menu){
        Menu menuById = menuService.selectMenuAllById(menu.getId());

        //如果菜单有被使用到，则不能被删除
        //1、菜单被角色关联，不能删除
        RoleMenu newRm = new RoleMenu();
        newRm.setMenuId(menuById.getId());
        boolean roleBoundMenus = menuService.checkRoleBoundMenus(newRm);
        if (roleBoundMenus){
            return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("该菜单已被【角色】关联，不能删除！");
        }

        if (StringUtils.isNull(menuById)){
            return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("该菜单不存在。");
        }else if (menuById.getType().equals(CommonConstant.TYPE_DIR)){
            //是父菜单就需要判断他是否有子菜单，如有有子菜单就不能删除
            int parentMenuCount = menuService.checkParentMenuHaveChildMenu(menu.getId());
            if (parentMenuCount>0){
                return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("【"+menuById.getMenuName()+"】下存在子菜单不能删除。");
            }
        }
        Menu newMenu = new Menu();
        newMenu.setId(menu.getId());
        newMenu.setStatus(menu.getStatus());
        boolean updateMenu = menuService.updateMenu(newMenu);
        if (updateMenu){
            return new Result().setCode(HTTPStatus.SUCCESS).setMessage("删除【"+menuById.getMenuName()+"】菜单成功。");
        }else{
            return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("删除【"+menuById.getMenuName()+"】菜单失败，请联系管理员。");
        }
    }
    @CacheEvict(value = "menus",allEntries = true)
    @RequiresPermissions("admin:menu:recover")
    @PutMapping("/recoverMenu")
    @ApiOperation("恢复菜单")
    public Result recoverMenu(@RequestBody Menu menu){
        boolean b = menuService.recoverMenu(menu);
        if (b){
            return new Result().setCode(HTTPStatus.SUCCESS).setMessage("菜单恢复成功。");
        }else {
            return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("菜单恢复失败，请联系管理员。");
        }
    }

    @Log(title = "菜单管理",businessType = BusinessType.DELETE)
    @CacheEvict(value = "menus",allEntries = true)
    @RequiresPermissions("admin:menu:completelyDelete")
    @DeleteMapping("/completelyDeleteMenu")
    @ApiOperation("彻底删除菜单")
    public Result completelyDeleteMenu(@NotNull(message = "编号不能为空") Integer id){
        Menu menuById = menuService.selectMenuAllById(id);
        if (StringUtils.isNull(menuById)){
            return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("该菜单不存在。");
        }else {
            boolean deleteMenuById = menuService.completelyDeleteMenuById(id);
            if (deleteMenuById){
                return new Result().setCode(HTTPStatus.SUCCESS).setMessage("彻底删除【"+menuById.getMenuName()+"】菜单成功。");
            }else{
                return new Result().setCode(HTTPStatus.BAD_REQUEST).setMessage("彻底删除【"+menuById.getMenuName()+"】菜单失败，请联系管理员。");
            }
        }
    }

}
